Repository navigation
test(testkit): add the testkit library for end-to-end suites - #4724
Open
matthewgrossman wants to merge 17 commits into
Open
matthewgrossman wants to merge 17 commits into
matthewgrossman wants to merge 17 commits into
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
🌿 Preview your docs: https://nvidia-preview-pr-4724.docs.buildwithfern.com/openshell |
matthewgrossman
marked this pull request as ready for review
October 19, 2026 22:37
matthewgrossman
requested review from
a team,
derekwaynecarr,
mrunalp and
sjenning
as code owners
October 19, 2026 22:37
6 tasks done
matthewgrossman
added this pull request to stack #4776
October 20, 2026 23:38
matthewgrossman
force-pushed
the
test/3954-land-testkit/matthewgrossman
branch
from
October 21, 2026 04:40
f595dd0 to
9c471d2
Compare
matthewgrossman
added a commit
that referenced
this pull request
Oct 21, 2026
Rebuilds the runner on the rebuilt migration, the current #4724 head and the tmachine paths from main. The tree is the rebuilt runner; the extra parent keeps this branch a fast-forward of what was pushed before.
Add tests/testkit as its own Cargo workspace: testkit, testkit-macros, and testkit-spec. testkit reads a target file, connects to the gateway through openshell-sdk, creates and cleans up sandboxes, and runs the installed CLI. #[testkit::test] requires a stable ID and a doc comment and declares capability requirements. testkit-ready waits for a target's gateway and CLI before tests run. Nothing uses testkit yet. The lockfile is seeded from the root lockfile so shared crates resolve to the same versions. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Nothing else builds testkit, so check it in Branch Checks and the matching mise tasks to catch openshell-sdk changes that break it. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Cleanup shared one two-minute budget across all of a test's sandboxes, so a slow delete left the rest with no time and could leak them on a shared gateway. Delete them concurrently, each with the full timeout. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Nothing reads test IDs or capability requirements until a runner, waivers, or result history exist, so remove the id and requires arguments and the target file's capabilities section. Both can return as optional attribute arguments without changing existing tests. With them gone, testkit-spec only checked the function shape and read the doc comment, so fold it into testkit-macros. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Replace the target file (OPENSHELL_TEST_TARGET) with the CLI's own gateway selection: OPENSHELL_GATEWAY_ENDPOINT, then OPENSHELL_GATEWAY, then the active gateway. A registered gateway's endpoint, auth mode, and mTLS material come from its CLI config directory. cx.cli runs OPENSHELL_BIN against the same gateway and workspace as the SDK. Suites now run unchanged under e2e/with-docker-gateway.sh and e2e/with-podman-gateway.sh, and environments need no extra file. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
The policy path creates the sandbox through gRPC and dropped the spec's labels without an error. Pass them in the create request. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
When OPENSHELL_GATEWAY_ENDPOINT is set, the CLI takes credentials from the gateway named by OPENSHELL_GATEWAY, or else the registered gateway with that endpoint. testkit connected without a client certificate instead, so an mTLS endpoint such as the one e2e/rust/e2e-vm.sh exports worked for cx.cli but not for the SDK. Resolve it the way the CLI does, and pass both the name and the endpoint to cx.cli. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
OPENSHELL_GATEWAY_ENDPOINT takes precedence over OPENSHELL_GATEWAY. Also mention OPENSHELL_BIN. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
#[testkit::test] left attributes such as #[ignore] and #[cfg] on the nested body function, where they have no effect on the test. Move them to the generated test, and reject a second test attribute such as Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> #[test] or #[tokio::test].
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
A testkit test panics on any failure, including an unreachable gateway or a failed cleanup, so #[should_panic] would let such a failure pass. Reject it and point to checking the expected failure in the body. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
matthewgrossman
force-pushed
the
test/3954-land-testkit/matthewgrossman
branch
from
October 21, 2026 20:41
6c1654e to
c8d4223
Compare
6 tasks done
5 of 6 tasks
Suites built on testkit exercise gateway resolution, the CLI wrapper, polling, errors, and cleanup against a real gateway. Keep one unit test for the macro's compile errors, which a passing suite never reaches, and drop the test-only seams the other tests needed. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
5 tasks done
matthewgrossman
removed this pull request from stack #4776
October 22, 2026 04:51
matthewgrossman
added this pull request to stack #4824
October 22, 2026 04:51
matthewgrossman
removed this pull request from stack #4824
October 22, 2026 05:29
matthewgrossman
added this pull request to stack #4825
October 22, 2026 05:30
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
testkit, a small library for writing end-to-end tests against a running OpenShell gateway through the Rust SDK. A test is a documentedasync fnmarked#[testkit::test]that runs with plaincargo nextest.openshellCLI does, so they run unchanged undere2e/with-docker-gateway.shande2e/with-podman-gateway.shwith no extra config.cx.cli(...)runs the CLI against the same gateway and workspace as the SDK.Stack
Part of a stack of four; each PR targets the one below it. The tmachine move (#4726) has merged, so the stack uses its
tests/tmachine/paths.SessionAPI, with a plan running on CI.Still to come, on top of #4774: moving the release lanes onto plans and deleting the old suites, once the plan has run the ported suites green.
Summary
Adds
tests/testkit/, a support library for SDK-driven end-to-end suites, as its own Cargo workspace. This is a small first step to get the crate into main and checked in CI. Nothing uses it yet. The existing suites move onto it in one follow-up migration (#4774, stacked on this PR) that also deletes the old suites. Suites added after that arrive one at a time.The code comes from @elezar's draft #4629 (head
673928804). This PR takes only the testkit portion, adapted to current main and cut down to what's needed today (see "Deferred and follow-ups" below).Related Issue
Part of #3954
Changes
tests/testkit/: thetestkitandtestkit-macroscrates, plus thetestkit-readybinary, taken from test(conformance): run conformance suites from test plans in tmachine environments #4629.async fnmarked#[testkit::test]with a required doc comment. Other attributes such as#[ignore]apply to the generated test.#[should_panic]is rejected, because a testkit test panics on any failure.openshellCLI does:OPENSHELL_GATEWAY_ENDPOINT, thenOPENSHELL_GATEWAY, then the active gateway. A registered gateway's endpoint and mTLS material come from its CLI config directory. Like the CLI, an endpoint takes its credentials fromOPENSHELL_GATEWAYor the registered gateway with that endpoint.cx.clirunsOPENSHELL_BINagainst the same gateway and workspace. Each test logs the gateway it used.Cargo.lockis re-seeded from the root lockfile, because main'sopenshell-sdkhas more dependencies than when test(conformance): run conformance suites from test plans in tmachine environments #4629 was cut.rust:lint,rust:format,rust:format:check, andtest:rustmise tasks now run fmt, clippy, and nextest for the testkit workspace. This follows test(conformance): run conformance suites from test plans in tmachine environments #4629'scf72f1108, restricted to testkit.tests/testkit/README.mdcovers writing a test, whatContextprovides, and running against a gateway.TESTING.md,AGENTS.md, andCONTRIBUTING.mdpoint to it.Deferred and follow-ups
Dropped from #4629's testkit
Each can come back as an optional addition, without changing tests written in the meantime:
id = "t-…"). Until a runner, waivers, or result history need them, the nextest name identifies a test.requires = [...]. These belong with the runner, which selects tests per environment. Until then, a suite excludes a test that an environment can't support with a nextest filter or#[ignore]. The first case is test(conformance): run conformance suites from test plans in tmachine environments #4629'sstopped_sandbox_keeps_workspace, which needs persistent workspaces.testkit-speccrate, for listing tests without compiling them. It returns with the runner's catalog, if that needs it.OPENSHELL_TEST_TARGET). It held a copy of the CLI's registered gateway plus capabilities, so testkit now reads the CLI's gateway config directly. As a result, step 3 no longer needs test(conformance): run conformance suites from test plans in tmachine environments #4629'sopenshell_clientrole change or the runner code that writestarget.yaml. The runner only setsOPENSHELL_GATEWAY(orOPENSHELL_GATEWAY_ENDPOINT) andOPENSHELL_BIN.Tests ported from #4629 must drop
idandrequires, because#[testkit::test]now takes no arguments.Rest of #4629, for later steps
Sessionlibrary, and the Ansible andconfig.nixchanges.e2e-suites.yml.a37ebe917). It matters once testkit is built into the Nix test archives. Until then,check-cargo-lockfiles.shalready validatestests/testkit/Cargo.lock.Follow-ups found while landing this
gateway.rsrepeats the CLI's lookup: the endpoint-to-registered-gateway match,metadata.jsonauth modes, and themtls/files. It also builds the mTLS channel itself, because the SDK leaves mTLS out. The copies can drift apart. When step 3 lands or tmachine needs the same lookup, move it intoopenshell-bootstrapor an SDK helper so the CLI, testkit, and tmachine share one implementation.mtls/path, as the CLI does. Gateway names with only letters, digits,.,-, and_are unaffected.cx.sandbox(...). Tests must delete anything else they create, such as providers. This is documented in the README. Extend the cleanup registry when suites create other resources often.tests/testkit/targetisn't covered by the Rust cache. This adds roughly 1–2 minutes to each Rust lint and test job. Caching it would add about 2 GB per platform cache. Revisit if suites make the build slower.supervisor_network_mode = "bridge".e2e/with-docker-gateway.shsets neither. Linux CI isn't affected. Consider setting bridge mode in the wrapper on macOS when the first testkit lane lands.Raised in review and left as is
Sandboxhelpers have no caller yet (for exampleconfig,draft_policy, andset_setting). They came from test(conformance): run conformance suites from test plans in tmachine environments #4629 for the suites in the next PR, so removing them now would only mean adding them back.Testing
cargo fmt --manifest-path tests/testkit/Cargo.toml --all -- --checkcargo clippy --locked --manifest-path tests/testkit/Cargo.toml --all-targets -- -D warningscargo nextest run --locked --config-file .config/nextest.toml --manifest-path tests/testkit/Cargo.toml(1 test: the macro rejects misuse. Gateway resolution, the CLI wrapper, and cleanup are exercised against a real gateway below and by the suites that adopt testkit.)tasks/scripts/check-cargo-lockfiles.shcoverstests/testkit/Cargo.lockmise run license:checkAgainst a real gateway
To check that testkit works end to end, I built a throwaway suite crate outside the repo. It depends on this branch's testkit and contains the six
sandbox_lifecycletests from #4629, plus a test that creates three sandboxes, checks thatcx.cli(["sandbox", "list"])shows them, and leaves them for cleanup. I ran it unchanged undere2e/with-docker-gateway.shon macOS with Docker Desktop. The wrapper's ownOPENSHELL_GATEWAYandOPENSHELL_BINwere the only configuration:e2e/with-docker-gateway.sh sh -c 'testkit-ready 120 && cargo nextest run --manifest-path <suite>/Cargo.toml --test-threads 1'testkit-readyresolved the wrapper's mTLS gateway, reported it healthy, and confirmed the CLI reaches it. All 7 tests passed in about 15s, andopenshell sandbox listshowed nothing left behind. Two#[ignore]tests, with the attribute above and below#[testkit::test], were skipped. With onlyOPENSHELL_GATEWAY_ENDPOINTset, ase2e/rust/e2e-vm.shdoes, testkit found the registered gateway's mTLS material, andtestkit-readyplus two tests passed.On Docker Desktop, sandboxes need either Docker Desktop's host networking turned on (Settings → Resources → Network) or
supervisor_network_mode = "bridge". Otherwise the supervisor cannot reach a gateway on the Mac's loopback. For this run I set bridge mode with a local, uncommitted change to the wrapper's gateway config.Checklist